package com.itany.corejava.code12_线程;

/**
 * @author 石小俊
 * @date 2023年05月15日 14:57
 */
public class Test05_线程安全问题 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t1 = new Thread(ticket, "窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");
        t1.start();
        t2.start();
        t3.start();
        // 当每一个线程均设置休眠时间时,此时运行后发现出现了有问题的票号
        // 例如:票号为0与-1
        // 假设此时的票卖到了最后一张,三个线程进来了
        // 第一个线程进来发现票号为1,大于0满足条件
        // 此时第一个线程休眠,第二个线程进来,发现票数还是1,大于0满足条件
        // 此时第二个线程休眠,第三个线程进来,发现票数还是1,大于0满足条件
        // 第三个线程休眠,第一个线程休眠时间到了,继续执行,票号为1
        // 第二个线程休眠时间到了,继续执行,票号为:1-1=0
        // 第三个线程休眠时间到了,继续执行,票号为:0-1=-1
        // 简单来讲
        // 当多个线程访问共享数据时,由于CPU时间片的切换, 导致第一个线程只执行了部分关键代码,尚未全部执行完成
        // 此时另一个线程参与进来,导致共享数据发生异常
        // 这就是线程安全问题
    }
}

//class Ticket implements Runnable {
//    private int num = 100;
//
//    @Override
//    public void run() {
//        synchronized (this) {
//            while (num > 0) {
//                try {
//                    Thread.sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                System.out.println(Thread.currentThread().getName() + "正在出票,票号为:" + num--);
//            }
//        }
//    }
//}

//class Ticket implements Runnable {
//    private int num = 1000;
//
//    @Override
//    public void run() {
//        while(true) {
//            synchronized (this) {
//                if (num > 0) {
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    System.out.println(Thread.currentThread().getName() + "正在出票,票号为:" + num--);
//                }
//            }
//        }
//    }
//}

class Ticket implements Runnable {
    private static int num = 1000;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                sellTicket();
            }
        }
    }

    public static synchronized void sellTicket() {
        if (num > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出票,票号为:" + num--);
        }
    }
}


